In [8]:
!pip -q install numpy matplotlib qutip scipy pillow

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as mpl_animation
import base64
from qutip import *
from IPython.display import display, HTML

plt.rcParams['animation.embed_limit'] = 90.0

# Physical parameters
J = 0.5 * 2 * np.pi   # Coupling strength
gamma = 0.2           # Decay rate
times = np.linspace(0, 10, 200)

# 2-qubit operators
sz1, sz2 = tensor(sigmaz(), qeye(2)), tensor(qeye(2), sigmaz())
sp1, sp2 = tensor(sigmap(), qeye(2)), tensor(qeye(2), sigmap())
sm1, sm2 = tensor(sigmam(), qeye(2)), tensor(qeye(2), sigmam())

# Exchange interaction Hamiltonian
H = J * (sm1 * sp2 + sp1 * sm2)
In [9]:
def create_cityscape_gif(states, title, filename):
    labels = ['|00⟩', '|01⟩', '|10⟩', '|11⟩']
    n = 4
    xpos, ypos = np.meshgrid(np.arange(n), np.arange(n))
    xpos, ypos = xpos.flatten(), ypos.flatten()
    zpos = np.zeros(n * n)
    dx = dy = 0.6 * np.ones(n * n)
    
    # Colors: blue=diagonal (populations), red=off-diagonal (coherences)
    is_diag = np.array([i == j for i in range(n) for j in range(n)])
    
    step = 5  # Sample every 5th frame
    sampled_states, sampled_times = states[::step], times[::step]
    fig = plt.figure(figsize=(6, 5))
    
    def update(frame):
        fig.clf()
        ax = fig.add_subplot(111, projection='3d')
        rho_abs = np.abs(sampled_states[frame].full()).flatten()
        colors = [(0.145, 0.388, 0.922, max(0.3, min(1, v+0.3))) if d else 
                  (0.863, 0.149, 0.149, max(0.3, min(1, v+0.3))) for d, v in zip(is_diag, rho_abs)]
        ax.bar3d(xpos, ypos, zpos, dx, dy, rho_abs, color=colors, edgecolor='black', linewidth=0.3)
        ax.set(xlabel='Column', ylabel='Row', zlabel='|ρᵢⱼ|', zlim=(0, 0.6))
        ax.set_xticks(np.arange(n) + 0.3); ax.set_xticklabels(labels)
        ax.set_yticks(np.arange(n) + 0.3); ax.set_yticklabels(labels)
        ax.view_init(elev=25, azim=45)
        ax.set_title(f"{title}\nt = {sampled_times[frame]:.2f}s", fontsize=10)
    
    ani = mpl_animation.FuncAnimation(fig, update, frames=len(sampled_states), interval=100)
    print(f"Rendering {filename}...")
    ani.save(filename, writer='pillow', fps=10)
    plt.close(fig)
    return filename

def display_cityscapes(gif_a, gif_b, case, noise_type):
    with open(gif_a, 'rb') as f: b64_a = base64.b64encode(f.read()).decode()
    with open(gif_b, 'rb') as f: b64_b = base64.b64encode(f.read()).decode()
    html = f'''<div style="text-align:center;"><h4>🏙️ {case} - {noise_type}</h4>
    <div style="display:flex;justify-content:center;gap:20px;">
    <img src="data:image/gif;base64,{b64_a}" style="max-width:45%;">
    <img src="data:image/gif;base64,{b64_b}" style="max-width:45%;"></div></div>'''
    display(HTML(html))

def simulate_decoherence(psi, case, noise_type='dephasing'):
    op1, op2 = (sz1, sz2) if noise_type == 'dephasing' else (sm1, sm2)
    
    # Independent baths vs Common bath
    c_ops_ind = [np.sqrt(gamma) * op1, np.sqrt(gamma) * op2]
    c_ops_com = [np.sqrt(gamma) * (op1 + op2)]
    
    result_ind = mesolve(H, psi, times, c_ops_ind)
    result_com = mesolve(H, psi, times, c_ops_com)
    
    # Plot concurrence
    conc_ind = [concurrence(rho) for rho in result_ind.states]
    conc_com = [concurrence(rho) for rho in result_com.states]
    
    noise_label = "Dephasing" if noise_type == 'dephasing' else "Energy Loss"
    plt.figure(figsize=(10, 5))
    plt.plot(times, conc_ind, label='Independent Baths')
    plt.plot(times, conc_com, label='Common Bath')
    plt.axhline(0, color='k', linewidth=0.5)
    plt.title(f'{case}: {noise_label}')
    plt.xlabel('Time (s)'); plt.ylabel('Concurrence')
    plt.legend(); plt.grid(True); plt.show()
    
    # Create cityscapes
    safe = case.replace(" ", "_").replace("(", "").replace(")", "")
    gif_a = create_cityscape_gif(result_ind.states, f'Independent ({noise_label})', f'city_{safe}_{noise_type}_ind.gif')
    gif_b = create_cityscape_gif(result_com.states, f'Common Bath ({noise_label})', f'city_{safe}_{noise_type}_com.gif')
    display_cityscapes(gif_a, gif_b, case, noise_label)

# Convenience wrappers for backward compatibility
def simulate_sigma_z(psi, case): simulate_decoherence(psi, case, 'dephasing')
def simulate_sigma_m(psi, case): simulate_decoherence(psi, case, 'energy_loss')
In [10]:
def project_to_logical(states):
    """Project to logical subspace: |0_L⟩=|01⟩, |1_L⟩=|10⟩"""
    return [Qobj([[(ket2dm(s) if isket(s) else s).full()[1,1], (ket2dm(s) if isket(s) else s).full()[1,2]], 
                  [(ket2dm(s) if isket(s) else s).full()[2,1], (ket2dm(s) if isket(s) else s).full()[2,2]]]) for s in states]

def get_bloch_coords(states):
    """Get Bloch coordinates from states"""
    logical = project_to_logical(states)
    return ([float(np.real(expect(sigmax(), r))) for r in logical],
            [float(np.real(expect(sigmay(), r))) for r in logical],
            [float(np.real(expect(sigmaz(), r))) for r in logical])

def run_dfs_comparison_z():
    """Compare DFS Protected vs Unprotected under phase noise"""
    psi0, t, g = tensor(basis(2, 0), basis(2, 1)), np.linspace(0, 10, 100), 0.3
    w = 1.0 * 2 * np.pi
    H_full = 0.5 * w * (sz1 + sz2) + J * (sm1 * sp2 + sp1 * sm2)
    
    # Simulate both scenarios
    res_dfs = mesolve(H_full, psi0, t, [np.sqrt(g) * (sz1 + sz2)])
    res_sep = mesolve(H_full, psi0, t, [np.sqrt(g) * sz1, np.sqrt(g) * sz2])
    
    # Get Bloch data
    xd, yd, zd = get_bloch_coords(res_dfs.states)
    xs, ys, zs = get_bloch_coords(res_sep.states)
    
    # Plot Bloch spheres side by side
    fig = plt.figure(figsize=(12, 5))
    for i, (x, y, z, title, color) in enumerate([
        (xd, yd, zd, "DFS Protected (Common Bath), Phase Noise", 'g'),
        (xs, ys, zs, "Unprotected (Separate Baths), Phase Noise", 'r')]):
        ax = fig.add_subplot(1, 2, i+1, projection='3d')
        b = Bloch(axes=ax)
        b.zlabel = ['$|01\\rangle$', '$|10\\rangle$']
        b.point_color = color
        b.vector_color = [color]
        b.point_marker = ['o']; b.point_size = [15]; b.view = [-40, 30]
        b.add_points([x, y, z], meth='s')
        b.add_vectors([x[-1], y[-1], z[-1]])
        b.render()
        ax.set_title(title, fontsize=12, fontweight='bold', color=color)
    plt.tight_layout(); plt.show()
    
    # Plot purity comparison
    def calc_len(states):
        xs, ys, zs = get_bloch_coords(states)
        return [np.sqrt(x**2 + y**2 + z**2) for x, y, z in zip(xs, ys, zs)]
    plt.figure(figsize=(10, 4))
    plt.plot(t, calc_len(res_dfs.states), 'g-', lw=2, label='DFS Protected')
    plt.plot(t, calc_len(res_sep.states), 'r-', lw=2, label='Unprotected')
    plt.axhline(1, color='k', ls='--', alpha=0.5, label='Ideal')
    plt.ylim(0, 1.1); plt.xlabel('Time (s)'); plt.ylabel('Bloch Vector Length')
    plt.title('Information Retention - Phase Noise γ=0.3', fontweight='bold')
    plt.legend(); plt.grid(alpha=0.3); plt.show()

def run_dfs_comparison_m():
    """Compare DFS Protected vs Unprotected under phase noise"""
    psi0, t, g = tensor(basis(2, 0), basis(2, 1)), np.linspace(0, 10, 100), 0.3
    w = 1.0 * 2 * np.pi
    H_full = 0.5 * w * (sz1 + sz2) + J * (sm1 * sp2 + sp1 * sm2)
    
    # Simulate both scenarios
    res_dfs = mesolve(H_full, psi0, t, [np.sqrt(g) * (sm1 + sm2)])
    res_sep = mesolve(H_full, psi0, t, [np.sqrt(g) * sm1, np.sqrt(g) * sm2])
    
    # Get Bloch data
    xd, yd, zd = get_bloch_coords(res_dfs.states)
    xs, ys, zs = get_bloch_coords(res_sep.states)
    
    # Plot Bloch spheres side by side
    fig = plt.figure(figsize=(12, 5))
    for i, (x, y, z, title, color) in enumerate([
        (xd, yd, zd, "DFS Protected (Common Bath), Energy Loss Noise", 'g'),
        (xs, ys, zs, "Unprotected (Separate Baths), Energy Loss Noise", 'r')]):
        ax = fig.add_subplot(1, 2, i+1, projection='3d')
        b = Bloch(axes=ax)
        b.zlabel = ['$|01\\rangle$', '$|10\\rangle$']
        b.point_color = color
        b.vector_color = [color]
        b.point_marker = ['o']; b.point_size = [15]; b.view = [-40, 30]
        b.add_points([x, y, z], meth='s')
        b.add_vectors([x[-1], y[-1], z[-1]])
        b.render()
        ax.set_title(title, fontsize=12, fontweight='bold', color=color)
    plt.tight_layout(); plt.show()
    
    # Plot purity comparison
    def calc_len(states):
        xs, ys, zs = get_bloch_coords(states)
        return [np.sqrt(x**2 + y**2 + z**2) for x, y, z in zip(xs, ys, zs)]
    plt.figure(figsize=(10, 4))
    plt.plot(t, calc_len(res_dfs.states), 'g-', lw=2, label='DFS Protected')
    plt.plot(t, calc_len(res_sep.states), 'r-', lw=2, label='Unprotected')
    plt.axhline(1, color='k', ls='--', alpha=0.5, label='Ideal')
    plt.ylim(0, 1.1); plt.xlabel('Time (s)'); plt.ylabel('Bloch Vector Length')
    plt.title('Information Retention - Energy Loss Noise γ=0.3', fontweight='bold')
    plt.legend(); plt.grid(alpha=0.3); plt.show()

Final Project TN3156¶

Authors: Matei Canavea, Casian Chiriac, Teodor Neagoe, Ivo van der Dussen (Group 13)¶

Two coupled TLS: the effect of decoherence on entanglement¶

Introduction¶

One of the major difficulties of quantum computing is the decoherence of Two Level Systems (TLS). This loss of information is non reversible and thus creates issues with information processing inside a quantum computer. From this, it is easy to see why preventing decoherence is of great importance in this field of computing.

One of the main causes of decoherence is noise. Noise causes dephasing in a qubit and thus leads to loss of information. For this project, a system of two coupled TLS's will be discussed. We will show how noise affects this two TLS system and simulate the system in QuTiP with varying parameters to find the most coherent system.

Description of the Physical Problem Being Simulated¶

Like mentioned before, our open system consists of two identical TLS's (e.g. Transmon Qubits, Spin Qubits etc.) which are coupled to eachother and thus, are able to exchange information. We will model the environment in 2 different ways: 1 collective "bath", which contains both TLS's and 2 seperate baths, each containing 1 TLS. In addition, we will also test 2 different kinds of subspaces: the singlet subspace and the triplet subspace. From testing all combinations of these parameters, we will be able to find the most noise-resistant configuration for our system.

For this system, we use a Hamiltonian with some approximations: $H = H_0 + H_1 + H_{int}$. The important piece of this Hamiltonian is $H_{int}$. This interaction Hamiltonian looks like this after approximations: $H_{int} = J(\sigma_{+}^{(1)}\sigma_{-}^{(2)} + h.c.)$. For this Hamiltonian, the Rotating-Wave Approximation (RWA) was used. If we assume $J << \omega$ , we can neglect terms that don't conserve energy (like $\sigma_{+}^{(1)}\sigma_{+}^{(2)}$ and $\sigma_{-}^{(1)}\sigma_{-}^{(2)}$), since these terms oscillate rapidly, thus being able to be equated to 0. Also, we apply the TLS approximation, stating that the qubits are perfect Two Level Systems, thus ignoring leakage to higher levels (such as $\ket{2}$, $\ket{3}$ etc.). Finally, like mentioned before, we assume 2 identical qubits, with exactly the same energy levels.

Based on physical intuition, we expect the system in the singlet subspace with the collective bath to be most resilient to noise, because of the anti-symmetrical nature of the singlet state and the symmetrical interaction to noise between both TLS's, respectively.

Aim and Scope of the Project¶

The main goal of this project is noise reduction. Using simulations inside of QuTiP, we will try to answer the following questions:

  • Is it possible to make the system consisting of two TLS's insensitive to noise with our parameters?
  • Against what kind of noise can our system be protected?
  • What would happen if we were to use more qubits?

Techniques and Approach¶

To answer these questions, we will plot concurrence graphs, to see how entanglement evolves through time while noise acts as decoherence. Concurrence is a measure of entanglement, ranging from 0 (no entanglement) to 1 (maximal entanglement). To calculate concurrence, we have defined a simplified interaction Hamiltonian using raising and lowering operators, like mentioned before. We use the concurrence() function, which is specifically defined for a 2-qubit system. The concurrence() function uses Wootters formula for calculating concurrence. This formula takes the density matrix of the system, multiplies it with it's own spin-flipped version and calculates all eigenvalues of the resulting matrix. All eigenvalues are then combined and a single value for concurrence is obtained: $C(\rho) = \max\{0, \lambda_1 - \lambda_2 - \lambda_3 ...\}$. (W. K. Wootters (1998), “Entanglement of Formation of an Arbitrary State of Two Qubits”)

To plot the concurrence against time, we use the Lindblad Master Equation to evolve the state vector $\ket{\Psi}$ through time. The Lindblad Master Equation can be solved in QuTiP by using the function mesolve(). After supplying this function with arguments H (Hamiltonian), $\rho_0$ (initial state vector or density matrix) and c_ops (collapse operator, in our case $\sigma_-$), the function uses $\dot{\rho} = \frac{i}{\hbar}[H, \rho] + \sum\limits_{i}\gamma_{i}(L_{i} \rho L_{i}^{\dagger} - \frac{1}{2} \{L_{i}^{\dagger} L_{i}, \rho\})$. (G. Lindblad (1976), "On the generators of quantum dynamical semigroups", for the Lindbladian and QuTiP documentation (https://qutip.org/docs/4.0.2/modules/qutip/mesolve.html) to get the time evolution of the state, which we can then plug into the concurrence() function)

For additional visualisation, we can also plot the Bloch sphere and cityscape:

  • The Bloch sphere can easily be plotted using bloch(). This class gives the user a blank canvas, which then can be filled with, for example, a density matrix. The class then, when requested, calculates the expectation values of the Pauli-matrices. It uses these values as 3D coordinates and plots vectors inside the Bloch sphere.
  • A cityscape is a 3D visualisation of the density matrix. Each element $\rho_{ij}$ in the density matrix gets a "building. The height of the building corresponds to the absolute value of the element $\rho_{ij}$. The diagonal values represent the probability of finding the system in that state. The off-diagonal values represent coherence.

Simulating the environments of the system is straightforward. We define the collapse operator c_ops in 2 different ways:

  • For the seperate bath, we defined two collapse operators: {$\sqrt{\gamma} \sigma_{-}^{(1)}$, $\sqrt{\gamma} \sigma_{-}^{(2)}$} and {$\sqrt{\gamma} \sigma_{z}^{(1)}$, $\sqrt{\gamma} \sigma_{z}^{(2)}$}. Here, $\gamma$ represents the "damping rate", $\sigma_{-}^{(i)}$ represents the lowering operator associated with qubit $i$ and $\sigma_{z}^{(i)}$ represents the phase operator associated with qubit $i$. Note that in the field of Quantum Information, the $\ket{1}$ refers to the ground state and $\ket{0}$ state refers to the excited state. So, the lowering operator transforms $\ket{0}$ into $\ket{1}$. In this definition, you can clearly see that we use two seperate collapse operators, one for phase, and one for energy loss.
  • For the common bath, we defined the collapse operators as $\sqrt{\gamma} (\sigma_{-}^{(1)} + \sigma_{-}^{(2)})$ and $\sqrt{\gamma} (\sigma_{z}^{(1)} + \sigma_{z}^{(2)})$. Unlike the seperate bath, we combine both lowering operators by taking their sum. This models a common bath, in which both qubits exist.

For the "best" parameters, we will apply a gate while noise tries to decohere the system. This process will also be visualised using a concurrence graph and a Bloch sphere.

Results¶

After running simulations inside of QuTiP and analysing the outputs, these were the following results:

Case 1: Triplet subsystem¶

In this case, we start with the maximally entangled triplet state ($\ket{\Psi_{+}} = \frac{\ket{01} + \ket{10}}{\sqrt{2}}$). Like mentioned before, we plot the concurrence graph for this case, to see how coherence evolves over time, influenced by the environment. For extra visualisation, we also included cityscapes. These figures can be seen below.

In [11]:
simulate_sigma_z((ket("01") + ket("10")).unit(), "Symmetrical Triplet State")
simulate_sigma_m((ket("01") + ket("10")).unit(), "Symmetrical Triplet State")
No description has been provided for this image
Rendering city_Symmetrical_Triplet_State_dephasing_ind.gif...
Rendering city_Symmetrical_Triplet_State_dephasing_com.gif...

🏙️ Symmetrical Triplet State - Dephasing

No description has been provided for this image No description has been provided for this image
No description has been provided for this image
Rendering city_Symmetrical_Triplet_State_energy_loss_ind.gif...
Rendering city_Symmetrical_Triplet_State_energy_loss_com.gif...

🏙️ Symmetrical Triplet State - Energy Loss

No description has been provided for this image No description has been provided for this image

In the first concurrence graph, you can see that the coherence in the seperate bath case rapidly declines, but the coherence in the common bath case stays constant at a value of 1. The same can be seen in the cityscapes. The seperate bath shows the blue "buildings" preserving their height, but the red coherence buildings collapsing. Coherence is thus lost. For the common bath, the cityscape stays constant. This means that the triplet state is insensitive to dephasing when both qubits are in the same bath. In the second concurrence graph, it is immediately clear that the environment noise has a large, negative effect on coherence in the triplet state for both bath models. When looking at the cityscapes, it becomes apparent that the state collapses to $\ket{11}$, which is the lowest energy state of the system.

Case 2: Singlet Subsystem¶

In this case, we start with the maximally entangled singlet state ($\ket{\Psi_{-}} = \frac{\ket{01} - \ket{10}}{\sqrt{2}}$). The concurrence graphs and cityscapes can be seen below.

In [12]:
simulate_sigma_z((ket("01") - ket("10")).unit(), "Anti-symmetrical Singlet State")
simulate_sigma_m((ket("01") - ket("10")).unit(), "Anti-symmetrical Singlet State")
No description has been provided for this image
Rendering city_Anti-symmetrical_Singlet_State_dephasing_ind.gif...
Rendering city_Anti-symmetrical_Singlet_State_dephasing_com.gif...

🏙️ Anti-symmetrical Singlet State - Dephasing

No description has been provided for this image No description has been provided for this image
No description has been provided for this image
Rendering city_Anti-symmetrical_Singlet_State_energy_loss_ind.gif...
Rendering city_Anti-symmetrical_Singlet_State_energy_loss_com.gif...

🏙️ Anti-symmetrical Singlet State - Energy Loss

No description has been provided for this image No description has been provided for this image

The singlet state behaves the exact same way when dephasing occurs: the seperate bath case shows decoherence, yet the common bath case shows insensitivity to decoherence due to dephasing. When considering energy loss, differences start to show. Like the triplet state, the singlet state decoheres due to energy loss, when both qubits are in seperate baths. Unlike the triplet state, though, the singlet state does not decohere due to energy loss when both qubits are in the same bath. The same is apparent from the cityscapes. The cityscapes for dephasing is the exact same as the triplet case, but the energy loss cityscapes show differences. When in independent baths, the state faalls back to $\ket{11}$, just like before. However, unlike with the triplet case, the cityscape for the common bath does not change with time, indicating insensitivity to energy loss due to noise. This means that, when both qubits feel the same noise, the singlet state does not decohere due to dephasing or energy loss.

This is because of the anti-symmetrical nature of the singlet state. The singlet state ($\ket{\Psi_{-}} = \frac{\ket{01} - \ket{10}}{\sqrt{2}}$) is insensitive to dephasing in the common bath case. This is because $\sigma_{z}^{tot} \ket{\Psi_{-}} = (\sigma_{z}^{(1)} + \sigma_{z}^{(2)})(\ket{01} - \ket{10}) = (\sigma_{z}^{(1)} + \sigma_{z}^{(2)})(\ket{01}) - (\sigma_{z}^{(1)} + \sigma_{z}^{(2)})(\ket{10}) = \ket{01} - \ket{01} + \ket{10} - \ket{10} = 0$. A similar phenomenon is described by the experiment in the paper by Governale et al (2001). "Decoherence and dephasing in coupled Josephson-junction qubits"

This state is also insensitive to decoherence due to energy loss. This is because $\sigma_{-}^{tot} \ket{\Psi_{-}} = (\sigma_{-}^{(1)} + \sigma_{-}^{(2)})(\ket{01} - \ket{10}) = (\sigma_{-}^{(1)} + \sigma_{-}^{(2)})(\ket{01}) - (\sigma_{-}^{(1)} + \sigma_{-}^{(2)})(\ket{10}) = \ket{11} - \ket{11} = 0$. The singlet subspace described here is an example of a Decoherence-Free Subspace (DFS), explored in detail by Campagnano, G., Hamma, A., & Weiss, U. (2009). "Decoherence and entanglement dynamics of coupled qubits".

Applying a X-gate to the system¶

To show how a DFS might be useful in practice, we will apply a X-gate in this example. First, we need to redefine our qubits. We have to combine both qubits in a particular way to create new "logical qubits". The reason why we need to do this can be seen in the Von Neumann entropy: For a pure state, the Von Neumann entropy is 0, per definition. This means that the state of the system is fully known. However, the seperate qubits have a Von Neumann entropy of $\ln{2}$. This is because the seperate qubits are in a maximally mixed state, which results in maximal entropy. Because of this, all stored information of this system is contained in the entanglement of the two qubits. So we need to find a way to compute with two qubits as if they were one qubit.

We define the logical qubits as: $\ket{0_{L}} = \ket{01}$ and $\ket{1_{L}} = \ket{10}$. Using these definitions for the logical qubits, we can plot a "logical Bloch sphere". This works, like mentioned before, with the bloch() function in QuTiP. To use the logical qubits instead of the standard qubits inside the bloch sphere, we need to make some modifications. To change the standard 4x4 qubit matrix to the 2x2 logical qubit matrix, we manually extract the correct elements. Then, we plot the bloch sphere as usual. We apply a X-gate to this system and visualise the result with the bloch sphere. Below you can see this bloch sphere and a graph of the length of the vector inside the bloch sphere.

In [13]:
run_dfs_comparison_z()
run_dfs_comparison_m()
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image

In this figure, you can see that the system is fully protected against phase noise when in DFS (the green circle inside the first bloch sphere, cause by the X gate, is unperturbed). The second Bloch sphere shows that, when the qubits are in seperate baths, the vector spirals from the edge of the sphere to the origin, indicating loss of information. In the third Bloch sphere, oddly enough, energy loss does seem to affect the system. The vector does not stay at the edge of the sphere, but rather also decreases in length (which indicates information loss). The same holds true for Bloch sphere number four. This is counterintuitive when looking back at what we discussed before. The issue seems to be the choice of logical qubit. We restrict our system to states $\ket{0_{L}} = \ket{01}$ and $\ket{1_{L}} = \ket{10}$. However, the only state with a total spin of 0 is the singlet state. Thus, energy can still dissipate into the environment and the state can still fall back to $\ket{11}$. One fix for this is scaling up to four qubits. With four qubits, we are able to create two states which have a total spin of 0: 2 pairs of singlets and a combination of triplet states with anti-parallel states, also resulting in a spin of 0. Redefining our logical qubits as a combination of 4 of these qubits would prevent this issue. Lidar, D. A., Chuang, I. L., & Whaley, K. B. (1998). "Decoherence-free subspaces for quantum computation" introduces DFS construction using multiple qubits to span subspaces annihilated by collective noise operators.

Summary and Outlook¶

To summarize, we tested various combinations of subspaces and environments to find out which combination would be most resilient to noise. We found out that 2 qubits in the singlet subspace and in a common bath will completely resilient to dephasing and energy loss due to noise. However, to compute with this DFS protected case, we would have to use four qubits, to prevent energy loss due to noise.

With more time, we would have liked to try and simulate a 4 qubit logical bit, to confirm whether it really is protected against energy loss. If this were to be possible, quantum computing could change a lot. Instead of spending resources on Quantum Error Correction codes, we could inherently and passively prevent errors, by scaling up to four-qubit logical qubits.

References¶

  1. W. K. Wootters, "Entanglement of Formation of an Arbitrary State of Two Qubits," Physical Review Letters, vol. 80, no. 10, pp. 2245–2248, 1998.
  2. G. Lindblad, "On the generators of quantum dynamical semigroups," Communications in Mathematical Physics, vol. 48, no. 2, pp. 119–130, 1976.
  3. QuTiP documentation, mesolve function. Available: https://qutip.org/docs/4.0.2/modules/qutip/mesolve.html.
  4. M. Governale, P. Schönheit, and U. Zülicke, "Decoherence and dephasing in coupled Josephson-junction qubits," Chemical Physics, vol. 268, no. 3, pp. 273–283, 2001.
  5. G. Campagnano, A. Hamma, and U. Weiss, "Decoherence and entanglement dynamics of coupled qubits,", 2009.
  6. D. A. Lidar, I. L. Chuang, and K. B. Whaley, "Decoherence-free subspaces for quantum computation," Physical Review Letters, vol. 81, no. 12, pp. 2594–2597, 1998.

Author contributions¶

Matei Canavea - Code exepriments implemntation, referencing, report review

Casian Chiriac - Bloch Sphere visualisations and basis for density matrix visualisations

Teodor Neagoe - Qubit decoherence live simulations, cityscapes

Ivo van der Dussen - Report and physical explanations